package parsexml;

import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
import parsexml.constant.XmlNodeConstant;
import parsexml.enity.XmlClass;
import parsexml.enity.XmlStudent;
import parsexml.enity.XmlSubject;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.*;

/**
 * @author 李栋
 * @version 1.0.0
 * @className ParseXmlBySaxTest.java
 * @createTime 2021年07月14日 21:16:00
 */
public class ParseXmlBySaxTest {

    private static final Logger logger = LoggerFactory.getLogger(ParseXmlBySaxTest.class);


    public InputStream getInputStream() throws FileNotFoundException {
        File file = new File("K:\\JavaTest\\src\\main\\java\\parsexml\\ClassDemo.xml");
        return new FileInputStream(file);
    }

    /**
     * 使用 Sax 解析逐行处理
     */
    @Test
    public void parseXmlBySax() {
        InputStream inputStream = null;
        try {
            inputStream = getInputStream();
            SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
            SAXParser saxParser = saxParserFactory.newSAXParser();
            XmlClass xmlClass = new XmlClass();
            saxParser.parse(inputStream, new XmlClassHandler(xmlClass));
            logger.info("test");
        } catch (Exception e) {
            logger.error("Error Occur:{}", e.getMessage(), e);
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                logger.error(e.getMessage(),e);
            }
        }
    }

    /**
     * 监听事件 按行处理
     */
    private static class XmlClassHandler extends DefaultHandler {

        /**
         * XmlClass
         */

        private final XmlClass xmlClass;

        /**
         * XmlStudent
         */
        private XmlStudent xmlStudent;

        /**
         * XmlSubject
         */
        private XmlSubject xmlSubject;

        /**
         * 是否 学生
         */
        boolean studentFlag;

        /**
         * 是否 科目
         */
        boolean subjectFlag;

        /**
         * 节点名称
         */
        private String nodeName;

        /**
         * 计数器
         */

        public XmlClassHandler(XmlClass xmlClass) {
            this.xmlClass = xmlClass;
        }

        @Override
        public void startDocument() {
            logger.info("开始处理 Xml ...");
        }

        @Override
        public void endDocument() {
            logger.info("结束处理 Xml ...");
        }

        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) {
            if (XmlNodeConstant.STUDENT.equals(qName)) {
                xmlStudent = new XmlStudent();
                studentFlag = true;
            }
            if (XmlNodeConstant.SUBJECT.equals(qName)) {
                xmlSubject = new XmlSubject();
                subjectFlag = true;
            }
            nodeName = qName;
        }

        @Override
        public void endElement(String uri, String localName, String qName) {
            if (XmlNodeConstant.STUDENT.equals(qName)) {
                xmlClass.getXmlStudents().add(this.xmlStudent);
                studentFlag = false;
            }
            if (XmlNodeConstant.SUBJECT.equals(qName)) {
                xmlStudent.getXmlSubjects().add(xmlSubject);
                subjectFlag = false;
            }
        }

        @Override
        public void characters(char[] chars, int start, int length) {
            String nodeValue = new String(chars, start, length);
            if (StringUtils.isEmpty(nodeValue.trim())) {
                return;
            }
            if (studentFlag && !subjectFlag) {
                switch (nodeName) {
                    case "NAME":
                        xmlStudent.setName(nodeValue);
                        break;
                    case "GENDER":
                        xmlStudent.setGender(nodeValue);
                        break;
                    case "STUDENT_SNO":
                        xmlStudent.setSno(nodeValue);
                        break;
                }
            }
            if (studentFlag && subjectFlag) {
                switch (nodeName) {
                    case "NAME":
                        xmlSubject.setSubjectName(nodeValue);
                        break;
                    case "SUBJECT_NO":
                        xmlSubject.setSubjectNo(nodeValue);
                        break;
                    case "SCORE":
                        xmlSubject.setScore(Float.parseFloat(nodeValue));
                        break;
                }
            }
            if (XmlNodeConstant.CLASS_NAME.equals(nodeName)) {
                xmlClass.setClassName(nodeValue);
            } else if (XmlNodeConstant.CLASS_CNO.equals(nodeName)) {
                xmlClass.setClassCno(nodeValue);
            }
        }

        @Override
        public void error(SAXParseException e) {
            logger.error("Error Occur:{}", e.getMessage());
        }

    }
}
